<?php

namespace App\Http\Services;

use App\Jobs\SendWechat;
use App\Models\Activity;
use App\Models\ActivitySessionTimes;
use App\Models\SubscribeMessage;
use App\Models\SubscribeMessageAccept;
use App\Models\SubscribeMessageBatch;
use App\Models\MessageTemplate;
use App\Repositories\BaseRepository;
use App\Repositories\SubscribeMessageAcceptRepository;
use App\Repositories\SubscribeMessageBatchRepository;
use App\Repositories\SubscribeMessageRepository;
use App\Repositories\MessageTemplateRepository;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Exception;

/**
 * 订阅消息服务
 *
 * Class SubscribeMessageService
 * @package App\Http\Services
 */
class SubscribeMessageService
{
    public function __construct()
    {
    }

    /**
     * 保存授权
     *
     * @param int    $contactId    志愿者ID
     * @param array  $templateIds  模板ID数组
     * @param int    $objectId     活动ID
     * @param string $objectType   目前只支持活动
     *
     * @throws Exception
     */
    public function addAccept(int $contactId, array $templateIds, int $objectId, string $objectType = 'activity'): void
    {
        $activity = Activity::find($objectId);
        if (!$activity || !$activity->id) {
            throw new Exception('活动不存在');
        }

        $SMAR = new SubscribeMessageAcceptRepository();
        $SMAR->addMulti($activity->team_id, $contactId, $templateIds, $objectId, $objectType);
    }

    /**
     * 保存批量发送任务
     *
     * @param string $type             类型，使用常量，名称前缀: SubscribeMessage::TYPE_
     * @param int    $adminId          管理员ID
     * @param array  $contactIds       志愿者ID数组
     * @param array  $content          消息内容
     * 消息内容会根据type不同，采用不同的校验和检查： \
     * SubscribeMessage::TYPE_CLOSE 和 SubscribeMessage::TYPE_CUSTOM \
     * array( \
     *      'title' => 'title', \
     *      'step' => 'step', \
     * ) \
     * SubscribeMessage::TYPE_INCLUDED 和 case SubscribeMessage::TYPE_LOSING \
     * array( \
     *      'result' => 'result', \
     *      'time' => 'time', \
     * ) \
     * SubscribeMessage::TYPE_GOOD_TIME \
     * array( \
     *      'name' => 'name', \
     *      'title' => 'title', \
     *      'time' => 'time', \
     * )
     * @param string $page             跳转小程序页面
     * @param int    $objectId         活动ID、场次ID
     * @param string $objectType       目前只支持活动、场次
     * @param int    $activityReportId 目前只支持活动、场次
     *
     * @return void
     * @throws Exception
     */
    public function addMessageBatch(
        string $type,
        int $adminId,
        array $contactIds,
        array $content,
        string $page,
        int $objectId
    ) {
        if (!isset(SubscribeMessage::TYPE_OPTIONS[$type])) {
            throw new Exception('type error:' . $type);
        }

        $template = MessageTemplate::where('type', '=', $type)->first();
        if (!$template) {
            throw new Exception('匹配模板发生错误');
        }

        $page = SubscribeMessage::TYPE_OPTIONS[$type]['page'];
        $templateId = $template->id;

        /*
        dump($type, $adminId, $contactIds, $content,$page, $objectId);
        */
        if($type == MessageTemplate::TYPE_DEFECT_VISIT){//缺访可补访提醒

        }else if($type == MessageTemplate::TYPE_HOME_VISIT_TAB){//填写家访表提醒

        }else if($type == MessageTemplate::TYPE_PREPARE_COURSE){//参与集体备课提醒

        }else if($type == MessageTemplate::TYPE_HOME_VISIT_FOLLOW){//填写家访随访提醒

        }else if($type == MessageTemplate::TYPE_MEETING){//参与月度例会提醒

        }else if($type == MessageTemplate::TYPE_HOME_VISIT_PATROL){//填写家访巡访提醒

        }else if($type == MessageTemplate::TYPE_PREPARE_COURSE_PATROL){//填写备课巡访提醒

        }else if($type == MessageTemplate::TYPE_MONTH_REPORT){//提交月度简报提醒

        }

        $SMAR = new SubscribeMessageAcceptRepository();
        $SMBR = new SubscribeMessageBatchRepository();
        $SMR = new SubscribeMessageRepository();

        $rs = $this->checkMsgContent($content, $template);
        if (!$rs) {
            throw new Exception('消息属性有误:' . json_encode($content, JSON_UNESCAPED_UNICODE) . '::' . json_encode($template->options));
        }

        $content = $rs;
        $subscribeMessageBatchId = $SMBR->add(
            $type,
            $teamId=0,
            $adminId,
            $content,
            $templateId,
            $objectId,
            ""
        );

        foreach ($contactIds as $contactId) {
            $accept = $SMAR->getAccept($contactId, $objectId, $templateId, MessageTemplate::getModule($type));

            $SM = $SMR->add(
                $contactId,
                $templateId,
                $page,
                $subscribeMessageBatchId,
                $accept->id ?? 0,
                !$accept || !$accept->id ? SubscribeMessage::STATUS_NO_AUTH : SubscribeMessage::STATUS_AWAIT
            );
            if ($SM && $accept && $accept->id) {
                $SMAR->used($accept);
            }

            // 此处增加发送任务添加dispatch的操作
            if ($SM) {
                //    SendWechat::dispatch(new SendWechat($SM->id))->onQueue('wechat');
                // 异步改为同步，正式上线前应该改为异步队列模式
                (new SendWechat($SM->id))->handle();
            }
        }
    }

    /**
     * 检查并过滤消息内容
     *
     * @param array $content
     * @param MessageTemplate $type
     * @return array|null
     */
    private function checkMsgContent(array $content, MessageTemplate $template)
    {
        $ret = [];
        $options = json_decode($template->options, true);

        foreach ($options as $key => $name) {
            if (isset($content[$key])) {
                $ret[$name] = $content[$key];
            } else {
                return null;
            }
        }

        return $ret;
    }

    /**
     * 批量发送列表，包含每个批量发送的状态统计（stat属性）
     *
     * @param int|null    $objectId   活动ID，缺省为NULL
     * @param string|null $objectType 目前只支持活动，缺省为：activity
     * @param int         $pageSize
     * @param int         $pageNumber
     *
     * @return LengthAwarePaginator
     */
    public function getBatch(int $objectId = null, string $objectType = 'activity', int $pageSize = 20, int $pageNumber = 1): LengthAwarePaginator
    {
        $query = SubscribeMessageBatch::query();
        if (!is_null($objectType)) {
            $query = $query->where('object_id', '=', $objectId)
                ->where('object_type', '=', $objectType);
        }
        $rs = $query->paginate($pageSize, '*', null, $pageNumber);
        $batchIds = [];
        foreach ($rs as $batch) {
            $batchIds[] = $batch->id;
        }
        if (count($batchIds) > 0) {
            $stat = SubscribeMessage::selectRaw('`subscribe_message_batch_id`, `status`, count(*) as num')
                ->whereIn('subscribe_message_batch_id', $batchIds)
                ->groupBy('subscribe_message_batch_id', 'status')
                ->get();
            $statDoc = [];
            foreach ($stat as $line) {
                if (!isset($statDoc[$line->subscribe_message_batch_id])) {
                    $statDoc[$line->subscribe_message_batch_id] = [];
                }
                $statDoc[$line->subscribe_message_batch_id][$line->status] = $line->num;
            }
            foreach ($rs as $batch) {
                $batch->stat = $statDoc[$batch->id];
            }
        }
        return $rs;
    }

    /**
     * 批量发送详情，一次批量发送的详细记录（开发时页面还没有定显���的字段，使用此方法时left join其他表关联到需要的字段���
     *
     * @param int $subscribeMessageBatchId 批量发送ID
     * @param int $pageSize
     * @param int $pageNumber
     *
     * @return LengthAwarePaginator
     */
    public function getSend(int $subscribeMessageBatchId, int $pageSize = 20, int $pageNumber = 1): LengthAwarePaginator
    {
        return SubscribeMessage::where('subscribe_message_batch_id', '=', $subscribeMessageBatchId)
            ->orderBy('updated_at', 'desc')
            ->paginate($pageSize, '*', null, $pageNumber);
    }

    /**
     * 保存要发出的数据
     *
     * @param $subscribeMessageId
     * @param $sendContent
     *
     */
    public function saveSendMessage($subscribeMessageId, $sendContent): void
    {
        $message = SubscribeMessage::find($subscribeMessageId);
        if ($message) {
            $message->send_content = $sendContent;
            $message->updated_at = date('Y-m-d H:i:s');
            $message->save();
        }
    }

    /**
     * 保存发送信息的接口返回
     *
     * @param int   $subscribeMessageId
     * @param array $resultContent
     * @param int   $status
     *
     * @return void
     */
    public function saveResultMessage(int $subscribeMessageId, array $resultContent, int $status): void
    {
        $message = SubscribeMessage::find($subscribeMessageId);
        if ($message) {
            $message->result_content = $resultContent;
            $message->updated_at = date('Y-m-d H:i:s');
            $message->status = $status;
            $message->save();
        }
    }

    /**
     * 获取批量发送列表
     *
     * @param string $kw
     * @param string $type
     * @param        $date
     * @param array  $where 支持team_id列表和activity_ids
     * @param int    $pageSize
     *
     * @return LengthAwarePaginator
     */
    public function list(string $kw, string $type, $date, array $where, int $pageSize = 20): LengthAwarePaginator
    {
        $query = SubscribeMessageBatch::query();
        if (count($where) > 0) {
            if ($where[0] === 'team_id') {
                $query = $query->whereIn($where[0], $where[1]);
            } elseif ($where[0] === 'activity_id') {
                $query = $query->whereIn('object_id', $where[1])
                    ->where('object_type', SubscribeMessage::OBJECT_TYPE_ACTIVITY);
            }
        }

        if (!empty($kw)) {
            $query = $query->where('content', 'like', "%{$kw}%");
        }

        if (!empty($type)) {
            $query = $query->where('type', '=', $type);
        }

        if (!empty($date) && count($date) === 3) {
            $query = $query->where([
                ['created_at', '>=', $date[0]],
                ['created_at', '<=', $date[2]],
            ]);
        }

        $rs = $query->orderBy('created_at', 'desc')
            ->paginate($pageSize);

        $activityIds = [];
        $SMBIds = [];
        foreach ($rs as $batch) {
            $SMBIds[] = $batch->id;
            if ($batch->object_type === SubscribeMessage::OBJECT_TYPE_ACTIVITY) {
                $activityIds[] = $batch->object_id;
            }
        }
        $activityDoc = [];
        if (count($activityIds) > 0) {
            $activityList = Activity::withTrashed()
                ->whereIn('id', $activityIds)
                ->get();

            foreach ($activityList as $activity) {
                $activityDoc[$activity->id] = $activity->title;
            }
        }
        $statDoc = [];
        if (count($SMBIds) > 0) {
            $stat = SubscribeMessage::whereIn('subscribe_message_batch_id', $SMBIds)
                ->selectRaw('subscribe_message_batch_id, status, count(*) as num')
                ->groupBy('subscribe_message_batch_id', 'status')
                ->get();
            foreach ($stat as $item) {
                if (!isset($statDoc[$item->subscribe_message_batch_id])) {
                    $statDoc[$item->subscribe_message_batch_id] = [];
                }
                $statDoc[$item->subscribe_message_batch_id][SubscribeMessage::STATUS_DOC[$item->status]['key']] = $item->num;
            }
        }

        foreach ($rs as $batch) {
            $batch->activityTitle = $activityDoc[$batch->object_id] ?? '';
            $batch->stat = $statDoc[$batch->id] ?? [];
        }

        return $rs;
    }
}
